home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / ruby / 1.8 / timeout.rb < prev    next >
Text File  |  2008-02-13  |  3KB  |  123 lines

  1. #--
  2. # = timeout.rb
  3. #
  4. # execution timeout
  5. #
  6. # = Copyright
  7. #
  8. # Copyright:: (C) 2000  Network Applied Communication Laboratory, Inc.
  9. # Copyright:: (C) 2000  Information-technology Promotion Agency, Japan
  10. #
  11. #++
  12. #
  13. # = Description
  14. #
  15. # A way of performing a potentially long-running operation in a thread, and
  16. # terminating it's execution if it hasn't finished within fixed amount of
  17. # time.
  18. #
  19. # Previous versions of timeout didn't use a module for namespace. This version
  20. # provides both Timeout.timeout, and a backwards-compatible #timeout.
  21. #
  22. # = Synopsis
  23. #
  24. #   require 'timeout'
  25. #   status = Timeout::timeout(5) {
  26. #     # Something that should be interrupted if it takes too much time...
  27. #   }
  28. #
  29.  
  30. module Timeout
  31.  
  32.   ##
  33.   # Raised by Timeout#timeout when the block times out.
  34.  
  35.   class Error < Interrupt
  36.   end
  37.   class ExitException < ::Exception # :nodoc:
  38.   end
  39.  
  40.   THIS_FILE = /\A#{Regexp.quote(__FILE__)}:/o
  41.   CALLER_OFFSET = ((c = caller[0]) && THIS_FILE =~ c) ? 1 : 0
  42.  
  43.   ##
  44.   # Executes the method's block. If the block execution terminates before +sec+
  45.   # seconds has passed, it returns true. If not, it terminates the execution
  46.   # and raises +exception+ (which defaults to Timeout::Error).
  47.   #
  48.   # Note that this is both a method of module Timeout, so you can 'include
  49.   # Timeout' into your classes so they have a #timeout method, as well as a
  50.   # module method, so you can call it directly as Timeout.timeout().
  51.  
  52.   def timeout(sec, klass = nil)
  53.     return yield if sec == nil or sec.zero?
  54.     raise ThreadError, "timeout within critical session" if Thread.critical
  55.     exception = klass || Class.new(ExitException)
  56.     begin
  57.       x = Thread.current
  58.       y = Thread.start {
  59.         sleep sec
  60.         x.raise exception, "execution expired" if x.alive?
  61.       }
  62.       yield sec
  63.       #    return true
  64.     rescue exception => e
  65.       rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o
  66.       (bt = e.backtrace).reject! {|m| rej =~ m}
  67.       level = -caller(CALLER_OFFSET).size
  68.       while THIS_FILE =~ bt[level]
  69.         bt.delete_at(level)
  70.         level += 1
  71.       end
  72.       raise if klass            # if exception class is specified, it
  73.                                 # would be expected outside.
  74.       raise Error, e.message, e.backtrace
  75.     ensure
  76.       y.kill if y and y.alive?
  77.     end
  78.   end
  79.  
  80.   module_function :timeout
  81.  
  82. end
  83.  
  84. ##
  85. # Identical to:
  86. #
  87. #   Timeout::timeout(n, e, &block).
  88. #
  89. # Defined for backwards compatibility with earlier versions of timeout.rb, see
  90. # Timeout#timeout.
  91.  
  92. def timeout(n, e = nil, &block) # :nodoc:
  93.   Timeout::timeout(n, e, &block)
  94. end
  95.  
  96. ##
  97. # Another name for Timeout::Error, defined for backwards compatibility with
  98. # earlier versions of timeout.rb.
  99.  
  100. TimeoutError = Timeout::Error # :nodoc:
  101.  
  102. if __FILE__ == $0
  103.   p timeout(5) {
  104.     45
  105.   }
  106.   p timeout(5, TimeoutError) {
  107.     45
  108.   }
  109.   p timeout(nil) {
  110.     54
  111.   }
  112.   p timeout(0) {
  113.     54
  114.   }
  115.   p timeout(5) {
  116.     loop {
  117.       p 10
  118.       sleep 1
  119.     }
  120.   }
  121. end
  122.  
  123.